package com.distribute.framework.core.web.util;

import com.distribute.framework.core.web.helper.Utils;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;


import com.distribute.framework.core.web.helper.WebHelper;

public class Ctrl  implements java.io.Serializable{
	Boolean isDefault = false;
	String title = null;//标题
	String action = null;//表单提交到哪
	String redirect = null;//转跳地址
	Boolean editable = null;//所有字段是否可编辑
	Boolean visible = null;//所有字段是否可见
	Boolean queryable = null;//所有字段是否查询
	Boolean listable = null;//所有字段是否列表
	Boolean canView = null;
	Boolean canQuery = null;
	Boolean canAdd = null;
	Boolean canEdit = null;
	Boolean canDel = null;
	Boolean canImport = null;
	Boolean canExport = null;
	Boolean canStats = null;
	Boolean[] canExp = null;
	List<Map> submits = new ArrayList();//有哪些提交按钮
	public static class Submit{//提交按钮
		String name;
		String value;
	}
	public static class FieldInfo{//字段设置
		Boolean editable = null;//所有字段是否可编辑
		Boolean visible = null;//所有字段是否可见
		Boolean queryable = null;//所有字段是否查询
		Boolean listable = null;//所有字段是否列表
		String defaultValue = null;//字段的默认值
	}
	Map<String,FieldInfo> fields = new HashMap();
	
	
	
	
	public HashMap e=new HashMap(){
		public Object get(Object key) {
			FieldInfo fieldSet = Ctrl.this.fields.get(key);
			if(fieldSet!=null && fieldSet.editable!=null)
				return fieldSet.editable;
			if(Ctrl.this.editable!=null)
				return Ctrl.this.editable;
			Ctrl defaultCtrl = Utils.getRequest("DEFAULT.CTRL");
			if(defaultCtrl!=null && !Ctrl.this.isDefault)
				return defaultCtrl.e.get(key);
			return null;
		}
	};
	public HashMap v=new HashMap(){
		public Object get(Object key) {
			FieldInfo fieldSet = Ctrl.this.fields.get(key);
			if(fieldSet!=null && fieldSet.visible!=null)
				return fieldSet.visible;
			if(Ctrl.this.visible!=null)
				return Ctrl.this.visible;
			Ctrl defaultCtrl = Utils.getRequest("DEFAULT.CTRL");
			if(defaultCtrl!=null && !Ctrl.this.isDefault)
				return defaultCtrl.v.get(key);
			return null;
		}
	};
	public HashMap q=new HashMap(){
		public Object get(Object key) {
			FieldInfo fieldSet = Ctrl.this.fields.get(key);
			if(fieldSet!=null && fieldSet.queryable!=null)
				return fieldSet.queryable;
			if(Ctrl.this.queryable!=null)
				return Ctrl.this.queryable;
			Ctrl defaultCtrl = Utils.getRequest("DEFAULT.CTRL");
			if(defaultCtrl!=null && !Ctrl.this.isDefault)
				return defaultCtrl.q.get(key);
			return null;
		}
	};
	public HashMap l=new HashMap(){
		public Object get(Object key) {
			FieldInfo fieldSet = Ctrl.this.fields.get(key);
			if(fieldSet!=null && fieldSet.listable!=null)
				return fieldSet.listable;
			if(Ctrl.this.listable!=null)
				return Ctrl.this.listable;
			Ctrl defaultCtrl = Utils.getRequest("DEFAULT.CTRL");
			if(defaultCtrl!=null && !Ctrl.this.isDefault)
				return defaultCtrl.l.get(key);
			return null;
		}
	};
	
	
	
	public static Ctrl fromJsonString(String jsonString,Boolean bDefaultCtrl) {
		if(Utils.empty(jsonString))return null;
		return fromMap((Map) WebHelper.eval(jsonString),bDefaultCtrl);
	}
	public static Ctrl fromMap(Map map,Boolean bDefaultCtrl) {
		if(map==null)
			return null;
		Ctrl ctrl = new Ctrl();
		ctrl.title = (String)map.get("title");
		ctrl.action = (String)map.get("action");
		ctrl.editable = (Boolean)map.get("editable");
		ctrl.visible = (Boolean)map.get("visible");
		ctrl.queryable = (Boolean)map.get("queryable");
		ctrl.listable = (Boolean)map.get("listable");
		ctrl.canView = (Boolean)map.get("canView");
		ctrl.canQuery = (Boolean)map.get("canQuery");
		ctrl.canAdd = (Boolean)map.get("canAdd");
		ctrl.canEdit = (Boolean)map.get("canEdit");
		ctrl.canDel = (Boolean)map.get("canDel");
		ctrl.canImport = (Boolean)map.get("canImport");
		ctrl.canExport = (Boolean)map.get("canExport");		
		ctrl.canStats = (Boolean)map.get("canStats");
		Boolean[] exps = (Boolean[]) map.get("canExp");
		if(exps!=null){
			for(int i=0;i<exps.length;i++)
				ctrl.canExp[i]=exps[i];
		}
		ctrl.redirect = (String)map.get("redirect");
		
		if(bDefaultCtrl==true){
			ctrl.isDefault = true;
			/*if(ctrl.editable==null)ctrl.editable=true;
			if(ctrl.visible==null)ctrl.visible=true;
			if(ctrl.queryable==null)ctrl.queryable=true;
			if(ctrl.listable==null)ctrl.listable=true;*/
			if(ctrl.canView==null)ctrl.canView=true;
			if(ctrl.canQuery==null)ctrl.canQuery=true;
			if(ctrl.canAdd==null)ctrl.canAdd=true;
			if(ctrl.canEdit==null)ctrl.canEdit=true;
			if(ctrl.canDel==null)ctrl.canDel=true;
			if(ctrl.canImport==null)ctrl.canImport=true;
			if(ctrl.canExport==null)ctrl.canExport=true;
			if(ctrl.canStats==null)ctrl.canStats=true;
			if(ctrl.canExp==null)ctrl.canExp = new Boolean[]{true,true,true,true,true,true,true,true,true,true,true,true,true,true};
			if(Utils.getRequest("CTRL")==null)
				Utils.setRequest("CTRL", new Ctrl());
		}
		
		//字段信息
		Map<String,Map> mapFields = (Map) map.get("fields");
		if(mapFields!=null){
			Set<String> keys = mapFields.keySet();
			for(String key:keys){
				Map fieldMap = mapFields.get(key);
				Ctrl.FieldInfo fieldSet = new Ctrl.FieldInfo();
				fieldSet.defaultValue = Utils.str(fieldMap.get("defaultValue"));
				fieldSet.visible = (Boolean) fieldMap.get("visible");
				fieldSet.editable = (Boolean) fieldMap.get("editable");
				fieldSet.listable = (Boolean) fieldMap.get("listable");
				fieldSet.queryable = (Boolean) fieldMap.get("queryable");
				ctrl.fields.put(key, fieldSet);
			}
		}
		
		//提交按钮
		List<Map> submits = (List) map.get("submits");
		if(submits!=null){
			ctrl.submits = submits;
		}
		
		ctrl.setBatch((String) map.get("visibles"),"visible");
		ctrl.setBatch((String) map.get("editables"),"editable");
		ctrl.setBatch((String) map.get("listables"),"listable");
		ctrl.setBatch((String) map.get("queryables"),"queryable");
		
		return ctrl;
	}
	
	//批量设置字段值
	private void setBatch(String strBatchs, String fieldName) {
		if(Utils.empty(strBatchs))return;
		String[] array = strBatchs.split(",");
		Field field;
		try {
			field = FieldInfo.class.getDeclaredField(fieldName);
		} catch (Exception e) {
			e.printStackTrace();
			return;
		}
		if(field==null)return;
		field.setAccessible(true);
		for(String item:array){
			String key = Utils.trim(item);
		    FieldInfo fieldSet = (FieldInfo)this.fields.get(key);
		    if (fieldSet == null) {
		      fieldSet = new FieldInfo();
		      this.fields.put(key, fieldSet);
		    }
		    try {
		    	field.set(fieldSet, true);
		    } catch (Exception e) {
				e.printStackTrace();
				continue;
			}
		}
	}
	
	
	public void setObjectDefaultValue(Object object){
		Map<String, FieldInfo> map = this.fields;
		if(map==null)return;
		Field[] fields = object.getClass().getDeclaredFields();
		for(Field field:fields){
			try{
				field.setAccessible(true);	
				if(field.get(object)!=null)continue;
				FieldInfo fieldInfo = map.get(field.getName());
				if(fieldInfo==null)continue;
				if(fieldInfo.defaultValue==null)continue;
				Class classType = getClassFromPrimitive(field.getType());
				Object objectValue = fieldInfo.defaultValue;
				if(objectValue==null)continue;
				String sObjectValue = objectValue.toString();
				if(Utils.empty(sObjectValue))continue;
				Object convertValue=null;
				if(classType.getSuperclass()==java.lang.Number.class){
					convertValue = classType.getMethod("valueOf", String.class).invoke(null,sObjectValue);
				}else if(classType==String.class){//java基本类型					
					convertValue = sObjectValue.toString();
				}else if(classType == java.util.Date.class){//日期类型					
					convertValue = new Date(Long.valueOf(sObjectValue));
				}
				field.set(object, convertValue);
			}catch(Exception ex){
				ex.printStackTrace();
			}
		}
	}
	
	
	
	/**
	 * 获取原始类对应的java类
	 * @param classType
	 * @return
	 */
	public static Class getClassFromPrimitive(Class classType){
		if(!classType.isPrimitive())return classType;
		String className = classType.getName();
		if(className.equals("byte"))return Byte.class;
		if(className.equals("short"))return Short.class;
		if(className.equals("int"))return Integer.class;
		if(className.equals("long"))return Long.class;
		if(className.equals("float"))return Float.class;
		if(className.equals("double"))return Double.class;	
		return null;
	}
	public String getTitle() {
		Ctrl defaultCtrl = Utils.getRequest("DEFAULT.CTRL");
		if(title==null && defaultCtrl!=null)
			return defaultCtrl.title;
		return title;
	}
	public String getAction() {
		Ctrl defaultCtrl = Utils.getRequest("DEFAULT.CTRL");
		if(action==null && defaultCtrl!=null)
			return defaultCtrl.action;
		return action;
	}
	public String getRedirect() {
		Ctrl defaultCtrl = Utils.getRequest("DEFAULT.CTRL");
		if(redirect==null && defaultCtrl!=null)
			return defaultCtrl.redirect;
		return redirect;
	}
	public Boolean getCanView() {
		Ctrl defaultCtrl = Utils.getRequest("DEFAULT.CTRL");
		if(canView==null && defaultCtrl!=null)
			return defaultCtrl.canView && Utils.or((Boolean)Utils.getRequest("canView"),false);
		return canView && Utils.or((Boolean)Utils.getRequest("canView"),false);
	}
	public Boolean getCanQuery() {
		Ctrl defaultCtrl = Utils.getRequest("DEFAULT.CTRL");
		if(canQuery==null && defaultCtrl!=null)
			return defaultCtrl.canQuery && Utils.or((Boolean)Utils.getRequest("canQuery"),false);
		return canQuery && Utils.or((Boolean)Utils.getRequest("canQuery"),false);
	}
	public Boolean getCanAdd() {
		Ctrl defaultCtrl = Utils.getRequest("DEFAULT.CTRL");
		if(canAdd==null && defaultCtrl!=null)
			return defaultCtrl.canAdd && Utils.or((Boolean)Utils.getRequest("canAdd"),false);
		return canAdd && Utils.or((Boolean)Utils.getRequest("canAdd"),false);
	}
	public Boolean getCanEdit() {
		Ctrl defaultCtrl = Utils.getRequest("DEFAULT.CTRL");
		if(canEdit==null && defaultCtrl!=null)
			return defaultCtrl.canEdit && Utils.or((Boolean)Utils.getRequest("canEdit"),false);
		return canEdit && Utils.or((Boolean)Utils.getRequest("canEdit"),false);
	}
	public Boolean getCanDel() {
		Ctrl defaultCtrl = Utils.getRequest("DEFAULT.CTRL");
		if(canDel==null && defaultCtrl!=null)
			return defaultCtrl.canDel && Utils.or((Boolean)Utils.getRequest("canDel"),false);
		return canDel && Utils.or((Boolean)Utils.getRequest("canDel"),false);
	}
	public Boolean getCanImport() {
		Ctrl defaultCtrl = Utils.getRequest("DEFAULT.CTRL");
		if(canImport==null && defaultCtrl!=null)
			return defaultCtrl.canImport && Utils.or((Boolean)Utils.getRequest("canImport"),false);
		return canImport && Utils.or((Boolean)Utils.getRequest("canImport"),false);
	}
	public Boolean getCanExport() {
		Ctrl defaultCtrl = Utils.getRequest("DEFAULT.CTRL");
		if(canExport==null && defaultCtrl!=null)
			return defaultCtrl.canExport && Utils.or((Boolean)Utils.getRequest("canExport"),false);
		return canExport && Utils.or((Boolean)Utils.getRequest("canExport"),false);
	}
	public Boolean getCanStats() {
		Ctrl defaultCtrl = Utils.getRequest("DEFAULT.CTRL");
		if(canStats==null && defaultCtrl!=null)
			return defaultCtrl.canStats && Utils.or((Boolean)Utils.getRequest("canStats"),false);
		return canStats && Utils.or((Boolean)Utils.getRequest("canStats"),false);
	}
	public Boolean[] getCanExp() {
		Ctrl defaultCtrl = Utils.getRequest("DEFAULT.CTRL");
		Boolean[] tempCanExp = canExp;
		if(canExp==null && defaultCtrl!=null)
			tempCanExp = defaultCtrl.canExp;
		Boolean[] requestCanExp = Utils.or((Boolean[])Utils.getRequest("canExp"),new Boolean[]{false,false,false,false,false,false,false,false,false,false,false});
		Boolean[] resultCanExp = new Boolean[Math.min(requestCanExp.length, tempCanExp.length)];
		for(int i=0;i<resultCanExp.length;i++)
			resultCanExp[i]=tempCanExp[i] && requestCanExp[i];
		return resultCanExp;
	}
	public List<Map> getSubmits() {
		Ctrl defaultCtrl = Utils.getRequest("DEFAULT.CTRL");
		if(submits==null && defaultCtrl!=null)
			return defaultCtrl.submits;
		return submits;
	}
	public HashMap getE() {
		return e;
	}
	public HashMap getV() {
		return v;
	}
	public HashMap getQ() {
		return q;
	}
	public HashMap getL() {
		return l;
	}
	
	
}